class Player(object):
    """A solution player for the SP."""
    def __init__(self, solution):
        self.solution       = solution  # Solution - that the player is executing
        self.warehouse      = None      # Warehouse - on which the player executes
        self.index          = None      # int - player position in the solution
        self.relocations    = None      # int - number of relocations done so far
        self.relocation_map = None      # {Action: int} - relocations done per action
        self.init()
        
    def init(self):
        self.warehouse = self.solution.instance.warehouse.deepcopy()
        self.index = 0
        self.relocations = 0
        self.relocation_map = dict()
        
    def step(self):
        if self.index == len(self.solution.actions):
            raise IndexError("end of solution reached - unable to step()")
        action = self.solution.actions[self.index]
        relocations = self.warehouse.execute(action)
        self.index += 1
        self.relocations += relocations
        self.relocation_map[action] = relocations
        return action
        
    def back(self):
        if self.index == 0:
            raise IndexError("beginning of solution reached - unable to back()")
        self.index -= 1
        action = self.solution.actions[self.index]
        self.warehouse.execute(action.reversed())
        self.relocations -= self.relocation_map.pop(action)
        return action
        
    def seek(self, pos):
        assert 0.0 <= pos <= 1.0
        if pos > self.progress:
            while pos > self.progress:
                self.step()
        else:
            while pos < self.progress:
                self.back()
                
    @property
    def progress(self):
        if len(self.solution.actions) == 0:
            return 0.0
        return float(self.index) / len(self.solution.actions)
        
    @property
    def ongoing(self):
        return self.index > 0
        
    @property
    def finished(self):
        return self.index >= len(self.solution.actions)
        
        
